import { BaseTable } from 'ali-react-table';
import { Button, Popconfirm } from 'antd';
import { action } from 'mobx';
import { observer } from 'mobx-react-lite';
import React, { HTMLAttributes, ReactElement } from 'react';
import { arrayHelpers, Form, useFormEnv } from 'react-antd-xform';
import { FormArrayLayoutInput } from 'react-antd-xform/dist/form/type';
import { calculateArrayTableData } from './calculateArrayTableData';

// 定义行属性接口
interface RowProps {
  rowIndex: number;
  trProps: HTMLAttributes<HTMLTableRowElement>;
  row: {
    hiddenItems: ReactElement[];
    effects?: ReactElement[];
    checks?: ReactElement[];
  };
}

// Row组件
function Row({ rowIndex, trProps, row }: RowProps): ReactElement {
  const hiddenItems = row.hiddenItems.map((item) =>
    React.cloneElement(item, { renderHiddenFormItemView: false }),
  );

  return (
    <Form.Object name={String(rowIndex)}>
      <tr {...trProps} />
      {row.effects}
      {row.checks}
      {hiddenItems}
    </Form.Object>
  );
}

function resolveOperationConfig(
  rowIndex: number,
  config: any,
  defaultConfig: any,
) {
  if (typeof config === 'function') {
    return resolveOperationConfig(rowIndex, config(rowIndex), defaultConfig);
  }
  if (typeof config === 'boolean') {
    return Object.assign(Object.assign({}, defaultConfig), {
      show: Boolean(config),
    });
  }
  return Object.assign(
    Object.assign(Object.assign({}, defaultConfig), {
      show: defaultConfig.show || Boolean(config),
    }),
    config,
  );
}

export interface ArrayTableOptions {
  defaultColumnWidth?: number;
  orderColumn?: any;
  style?: React.CSSProperties;
  className?: string;
  operations?: any;
  operationColumn?: any;
  tableImplementation?: React.ComponentType<any>;
  tableProps?: any;
}

export const TableRowOperations = observer(
  ({ operations, arrayModel, itemIndex }: any) => {
    const { isPreview } = useFormEnv();
    if (isPreview) {
      return null;
    }
    const delete_ = resolveOperationConfig(
      itemIndex,
      operations === null || operations === void 0 ? void 0 : operations.delete,
      {
        show: false,
        disabled: false,
        label: '删除',
        confirm: true,
      },
    );
    const move = resolveOperationConfig(
      itemIndex,
      operations === null || operations === void 0 ? void 0 : operations.move,
      { show: false, disabled: false },
    );
    const moveUp = resolveOperationConfig(
      itemIndex,
      operations === null || operations === void 0 ? void 0 : operations.moveUp,
      Object.assign(Object.assign({}, move), { label: '上移' }),
    );
    const moveDown = resolveOperationConfig(
      itemIndex,
      operations === null || operations === void 0
        ? void 0
        : operations.moveDown,
      Object.assign(Object.assign({}, move), { label: '下移' }),
    );
    const buttons = [
      ['moveUp', moveUp, arrayHelpers.moveUp],
      ['moveDown', moveDown, arrayHelpers.moveDown],
      ['delete', delete_, arrayHelpers.delete],
    ];
    return React.createElement(
      React.Fragment,
      null,
      buttons.map(([key, config, handler]) => {
        if (!config.show) {
          return null;
        }
        const callback = action(() => handler(arrayModel, itemIndex));
        if (key === 'delete' && config.confirm) {
          return React.createElement(
            Popconfirm,
            {
              key: key,
              title: '\u786E\u5B9A\u8981\u5220\u9664\u4E48\uFF1F',
              onConfirm: callback,
            },
            React.createElement(
              Button,
              {
                key: key,
                type: 'link',
                disabled: config.disabled,
              },
              config.label,
            ),
          );
        }
        return React.createElement(
          Button,
          {
            key: key,
            type: 'link',
            disabled: config.disabled,
            onClick: callback,
          },
          config.label,
        );
      }),
    );
  },
);

export function arrayTable({
  defaultColumnWidth,
  orderColumn,
  style,
  className,
  operations,
  operationColumn,
  tableImplementation: Table = BaseTable, // todo 后续可以默认替换为 ProTable
  tableProps,
}: ArrayTableOptions = {}) {
  return (input: FormArrayLayoutInput) => {
    const { arrayModel } = input;
    const { columns, dataSource } = calculateArrayTableData(input);
    const { components, ...restTableProps } = tableProps || {};
    if (orderColumn != null) {
      columns.unshift({
        name: '#',
        width: 50,
        lock: true,
        align: 'right',
        ...orderColumn,
        getValue(row: any): any {
          return row.itemIndex + 1;
        },
      });
    }

    if (operationColumn || operations) {
      // 操作列
      columns.push({
        name: '',
        width: 120,
        lock: true,
        getCellProps() {
          return { style: { padding: 8 } };
        },
        ...operationColumn,
        render(_: any, row: any) {
          return (
            <div>
              <TableRowOperations
                arrayModel={arrayModel}
                itemIndex={row.itemIndex}
                operations={operations}
              />
            </div>
          );
        },
      });
    }

    return (
      <Table
        className={className}
        style={style}
        primaryKey="rowKey"
        defaultColumnWidth={defaultColumnWidth}
        dataSource={dataSource}
        columns={columns}
        components={{ Row, ...components }}
        {...restTableProps}
      />
    );
  };
}

arrayTable.Group = (_props: any) => null;
